package com.GB26875_3_2011.message;

import com.GB26875_3_2011.config.ChannelManager;
import com.GB26875_3_2011.message.handler.MessageHandler;
import com.GB26875_3_2011.message.parser.MessageBodyParser;
import com.GB26875_3_2011.model.GB26875Message;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.timeout.IdleState;
import io.netty.handler.timeout.IdleStateEvent;
import lombok.extern.slf4j.Slf4j;

import java.net.InetSocketAddress;
import java.net.SocketAddress;

/**
 * @author 蒋仕国
 * @projectName GB26875_3_211
 * @ClassName MessageSimpleHandler
 * @date 2025-01-13 10:50
 * @Description: TODO []
 */
@Slf4j
@ChannelHandler.Sharable
public class MessageSimpleHandler extends SimpleChannelInboundHandler<GB26875Message> {



    /**
     * Is called for each message of type .
     * @param ctx the {@link ChannelHandlerContext} which this {@link SimpleChannelInboundHandler}
     * belongs to
     * @param msg the message to handle
     * @throws Exception is thrown if an error occurred
     */
    @Override
    protected void channelRead0(ChannelHandlerContext ctx, GB26875Message msg) throws Exception {
        String sourceAddressHex = msg.getSourceAddressHex();
        // 维护address的关系
        if (ChannelManager.get(sourceAddressHex) == null) {
            ChannelManager.add(sourceAddressHex, ctx.channel());
        }
        GB26875Message result = processing(msg);
        // 发送数据发【协议中未说明有分包情况】
        MessageContext.sendMessage(ctx.channel(),result);
    }



    private GB26875Message processing(GB26875Message message) {
        // commid
        int command = message.getCommandType().getCode();
        Integer parserId = null;
        if (message.getMessageBody() != null && message.getMessageBody().length > 0) {
            // 获取消息解析器
            parserId = message.getDataUnitType().getCode();
            MessageBodyParser parser = MessageContext.getParser(parserId);
            message.setMessageBodyObjs(parser.parseBody(message.getMessageBody()));
        }
        // 消息人员处理器
        MessageHandler handler = MessageContext.getHandler(command,parserId);
        return handler.handler(message);
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
        SocketAddress socketAddress = ctx.channel().remoteAddress();
        log.error("[发生异常] 异常信息: {}, 链接地址: {}", cause.getMessage(),socketAddress.toString());
        ChannelManager.remove(ctx.channel());
        cause.printStackTrace();
        ctx.close();
    }


    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
        if (evt instanceof IdleStateEvent) {
            IdleState state = ((IdleStateEvent) evt).state();
            SocketAddress socketAddress = ctx.channel().remoteAddress();
            if (state == IdleState.READER_IDLE) {
                log.warn("客户端: {}读取超时, 关闭连接", socketAddress);
                ChannelManager.remove(ctx.channel());
                ctx.close();
            } else if (state == IdleState.WRITER_IDLE) {
                log.warn("客户端: {}写入超时",socketAddress);
                ChannelManager.remove(ctx.channel());
                ctx.close();
            } else if (state == IdleState.ALL_IDLE) {
                log.warn("客户端: {}读取写入超时", socketAddress);
            }
        } else {
            super.userEventTriggered(ctx, evt);
        }
    }

    @Override
    public void handlerRemoved(ChannelHandlerContext ctx)  {
        log.info("一个客户端移除......" + ctx.channel().remoteAddress());
        ChannelManager.remove(ctx.channel());
        ctx.close(); //关闭连接
    }

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        super.channelActive(ctx);
        InetSocketAddress insocket = (InetSocketAddress) ctx.channel().remoteAddress();
        String clientIp = insocket.getAddress().getHostAddress();
        log.info("与服务端{}建立连接", clientIp);
    }

}
